import socket

# 创建一个TCP套接字
# TCP的套接字类型为SOCK_STREAM
# type=1
# socket.AF_INET： 使用IPv4地址
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 创建一个UDP套接字
# UDP的套接字类型为SOCK_DGRAM
# type=2
# socket.AF_INET： 使用IPv4地址
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

print(tcp_socket)   # <socket.socket fd=284, family=2, type=1, proto=0>
print(udp_socket)   # <socket.socket fd=288, family=2, type=2, proto=0>

print("=" * 50)
# TCP服务器绑定和监听
# socket绑定到一个指定的地址和端口
tcp_socket.bind(('127.0.0.1', 9000))
# 启动监听，最大连接数是5
tcp_socket.listen(5)
print("服务器已启动，等待客户端连接...")

# 接收和处理连接
# accept()方法是会阻塞的，直到有客户端连接
# accept方法会返回一新的套接字和客户端地址，新的套接字用于与客户端进行通信
client_socket,client_address = tcp_socket.accept()
print("客户端已连接：", client_address)

# 接收客户端数据
data = client_socket.recv(1024)
print("接收到的数据：", data.decode(encoding="utf-8"))

# 发送响应数给客户端
# sendall()方法保证发送所有数据，内部自动处理重试，直到全部分送完或出错
# 还有一个方法是send()它不保证一次性发送所有数据，可能只发送部分数据，需要手动检查返回值并循环发送剩余数据
client_socket.sendall("你好，客户端！".encode(encoding="utf-8"))

# 如果使用send检查并发送剩余的数扰可以像下面这样操作
# message = "你好，客户端！".encode()
# total_send = 0
# while total_send < len(message):
#     sent = client_socket.send(message[total_send:])
#     if sent == 0:
#         raise RuntimeError("连接已断开")
#     total_send += sent

# 关闭连接
client_socket.close()